﻿using HDJ.Framework.Core;
using NetworkCommsDotNet;
using NetworkCommsDotNet.Connections;
using NetworkCommsDotNet.Connections.TCP;
using NetworkCommsDotNet.Connections.UDP;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace HDJ.Framework.Core
{
    public static class NetworkClientManager
    {
        /// <summary>
        /// 是否连接成功回调
        /// </summary>
        public static CallBack<Connection, bool> OnConnected;
        public static CallBack<Connection> OnDisConnected;
        public static ConnectionInfo connectionInfo;
        public static Connection connection;

        public static ConnectionState ConState
        {
            get
            {
                return connectionInfo.ConnectionState;
            }
        }
        public static IPEndPoint ipEndPoint;

        public static bool isUDP;
        public static UDPOptions options;
        public static bool ConnectTCP(string ip, int port)
        {
            return Init(ip, port, false);
        }
        public static bool ConnectUDP(string ip, int port, UDPOptions options)
        {
            NetworkClientManager.options = options;
            return Init(ip, port, true);
        }
        private static bool Init(string ip, int port, bool isUDP)
        {
            if (connectionInfo != null && connectionInfo.ConnectionState == ConnectionState.Established)
            {
                Debug.LogError("已有连接！");
                return false;
            }
            RegisterEvent();

            IPAddress ipAdd;
            if (string.IsNullOrEmpty(ip) || ip =="127.0.0.1" || ip.ToLower()== "localhost")
            {
                IPAddress[] ips = NetworkUtils.GetLocalIP(AddressFamily.InterNetwork);
                ipAdd = ips[0];
                Debug.Log("IP :" + ip);
            }
            else
            {
                ipAdd = IPAddress.Parse(ip);
            }
   
            NetworkClientManager.isUDP = isUDP;
            ipEndPoint = new IPEndPoint(ipAdd, port);
            connectionInfo = new ConnectionInfo(ipEndPoint);
            try
            {
                if (isUDP)
                    connection = UDPConnection.GetConnection(connectionInfo, options);
                else
                    connection = TCPConnection.GetConnection(connectionInfo);
                connection.SendObject("Test Connect",new byte[] { 0 });
            }
            catch (Exception e)
            {
                if (OnConnected != null)
                {
                    OnConnected(connection, false);
                }
                Debug.LogError(e);
                return false;
            }
            if (OnConnected != null)
            {
                OnConnected(connection, true);
            }
            Debug.Log("连接成功 :"+ ipEndPoint);
            return true;
        }
        private static bool isRegisterEvent = false;
        private static void RegisterEvent()
        {
            if (isRegisterEvent) return;
            isRegisterEvent = true;

            //NetworkComms.AppendGlobalConnectionEstablishHandler((connct) =>
            //{
            //    Debug.Log("新连接 ：" + connct.ToString());
            //});
            //NetworkComms.AppendGlobalConnectionCloseHandler((com) =>
            //{
            //    Debug.Log("关闭连接 ：" + com.ToString());
            //});
            NetworkComms.AppendGlobalConnectionCloseHandler((com) =>
            {
                Debug.Log("关闭连接 ：" + com.ToString());
                if (OnDisConnected != null)
                    OnDisConnected(com);
            });

            Type baseType = typeof(ProtocolActionBase);
            Type sType = ReflectionUtils.GetTypeByTypeFullName("ProtocolReceiveActionDefine");

            Type[] types = ReflectionUtils.GetChildTypes(baseType);
            foreach (var item in types)
            {
                if (sType != null && item == sType)
                    continue;
                object obj = ReflectionUtils.CreateDefultInstance(item);
                if (obj != null)
                {
                    ((ProtocolActionBase)obj).Init();
                    Debug.Log("ProtocolActionBase Type Name :" + item.FullName);
                }
            }
        }
        public static returnObjectType SendReceiveObject<sendObjectType, returnObjectType>(string sendingPacketTypeStr, sendObjectType sendObject, int returnPacketTimeOutMilliSeconds=5000)
        {
           return connection.SendReceiveObject<sendObjectType, returnObjectType>(sendingPacketTypeStr, sendingPacketTypeStr + "_Receive", returnPacketTimeOutMilliSeconds, sendObject);
        }
        public static void SendObject<sendObjectType>(string sendingPacketTypeStr, sendObjectType sendObject)
        {
             connection.SendObject(sendingPacketTypeStr, sendObject);
        }
        public static void CloseConnection()
        {
            if (connection != null)
                connection.CloseConnection(false);
        }
       
      
    }

}
